package com.zhangzeqin.code.util;

import com.zhangzeqin.code.entity.User;

import java.io.File;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;

/**
 * 实现jdbc的curd操作
 * @author 张泽钦
 */
public class JdbcUtil {
    /**
     * 封装简化非DQL语句
     * @param sql 带占位符的SQL语句
     * @param params 占位符的值,值的个数等于?个数
     * @return 执行影响的行数
     */
    public static int executeUpdate(String sql,Object ... params) throws SQLException {
        //获取连接
        Connection connection = DruidTool.getConnection();

        //创建预编译statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //占位符赋值,设置?的值
        for (int i = 1; i <=params.length ; i++) {
            preparedStatement.setObject(i,params[i-1]);
        }
        //发送sql语句,返回影响行数
        int rows=preparedStatement.executeUpdate();

        //是否收回连接,需要考虑是不是事务
        if(connection.getAutoCommit()){
            //没有开启事务,正常回收连接
            DruidTool.recycleConnection(connection);
        }
        return rows;

    }

    /**
     * 封装简化DQL语句
     * @param sql 带占位符的SQL语句
     * @param params 占位符的值,值的个数等于?个数
     * @param
     */
    public static boolean Query(String sql,Object ... params) throws SQLException {
        //获取连接
        Connection connection = DruidTool.getConnection();

        //创建预编译statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //占位符赋值,设置?的值
        for (int i = 1; i <=params.length ; i++) {
            preparedStatement.setObject(i,params[i-1]);
        }

        //返回结果集
        ResultSet resultSet = preparedStatement.executeQuery();


        if (resultSet.next()){
            //是否收回连接,需要考虑是不是事务
            if(connection.getAutoCommit()){
                //没有开启事务,正常回收连接
                DruidTool.recycleConnection(connection);
            }
            resultSet.close();
            return true;
        }
        return false;

    }

    /**
     * 发送创建表的sql语句
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public static boolean creatTbale(String sql,Object ... params) throws SQLException {
        //获取连接
        Connection connection = DruidTool.getConnection();

        //创建预编译statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //占位符赋值,设置?的值
        for (int i = 1; i <=params.length ; i++) {
            preparedStatement.setObject(i,params[i-1]);
        }
        //发送sql语句,返回影响行数
        boolean execute = preparedStatement.execute();

        //是否收回连接,需要考虑是不是事务
        if(connection.getAutoCommit()){
            //没有开启事务,正常回收连接
            DruidTool.recycleConnection(connection);
        }
        return execute;

    }

    /**
     *从数据库获取表的全部信息
     * <T>声明一个泛型,不确定类型
     *    确定泛型 User.class T=User
     *    使用反射技术进行属性赋值
     * @param sql 执行的sql语句
     * @param params 传入的参数
     * @return 返回一个list集合
     */
    public static <T> ArrayList<T> selectAll(Class<T> clazz,String sql,Object...params) throws SQLException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        //获取连接
        Connection connection = DruidTool.getConnection();

        //创建预编译statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //占位符赋值,设置?的值
        if (params.length > 0 || params != null) {
            for (int i = 1; i <= params.length; i++) {
                preparedStatement.setObject(i, params[i - 1]);
            }
        }
        //定义一个集合
        ArrayList<T> list = new ArrayList<>();
        //结果集解析
        ResultSet resultSet = preparedStatement.executeQuery();
        /**
         * 获取结果集的元数据对象
         * 元数据对象有该结果集一共有几列,列名等信息
         */
        ResultSetMetaData metaData= resultSet.getMetaData();
        //获取结果集列数
        int columnCount = metaData.getColumnCount();

        //遍历结果集ResultSet,把查询结果中的一条一条记录,编程一个一个T对象,放到list中
        while(resultSet.next()){
            //调用类的无参构造函数实例化对象
            T t=clazz.newInstance();
            for (int i = 1; i <=columnCount ; i++) {
                //对象属性值
                Object value = resultSet.getObject(i);
                //获得指定列小角标的列的名称
                String propertyName = metaData.getColumnLabel(i);

                //反射,给对象的属性值赋值
                //获得属性名
                Field field=clazz.getDeclaredField(propertyName);
                System.out.println(propertyName);
                //可以设置私有的属性
                field.setAccessible(true);
                /**
                 * 参数1,要赋值的对象
                 * 参数2 具体的属性值
                 */
                field.set(t,value);
            }
            list.add(t);

            }
        //关闭资源
        if (resultSet.next()){
            //是否收回连接,需要考虑是不是事务
            if(connection.getAutoCommit()){
                //没有开启事务,正常回收连接
                DruidTool.recycleConnection(connection);
            }
            resultSet.close();
        }
        return list;
        }

    }